/*
 * smart-pwm-ss805x.c
 *
 * smart pwm driver for SS805X.
 *
 * Copyright (C) 2024 Sinh Micro, Inc.
 * Subject to the GNU Public License, version 2.
 *
 * Author: lixiang<lixiang@sinhmicro.com>
 * 
 * Encoding format: GB2312
 * Version: v1.2.2
 * Date: 2024-11-05
 */

#include "hal-config.h"
#include "hal-regs.h"

#include "types.h"
#include "system.h"
#include "gpio.h"
#include "timer.h"
#include "smart-pwm.h"

#if (defined(CONFIG_SYS_CHIP_SERIES_SS805X))

#if (CONFIG_USING_SMPWM0 == 1 || CONFIG_USING_SMPWM2 == 1)
void spwm_init(uint8_t spwm)
{
    uint16_t tmp;

#if (CONFIG_USING_SMPWM0 == 1)
    if (spwm == 0) {
    #if (CONFIG_USING_SMPWM0_CC0 == 1)
    PWMPOL = (PWMPOL & ~(1 << 0)) | (CONFIG_SMPWM0_CC0_POLOR << 0);
    
    tmp = T0_MAX_CNT_VAL_GET() - (T0_MAX_CNT_VAL_GET() - TIMER0_RELOAD_VALUE) \
          * CONFIG_SMPWM0_CC0_INIT_DUTY / 100;
    PWM0CMPL = tmp & 0xff;
    PWM0CMPH = tmp >> 8;

    PWMEN = (PWMEN & ~(1 << 0)) | (1 << 0);
    spwm_cc_disable(0, 0);
    #endif
    }
#endif

#if (CONFIG_USING_SMPWM2 == 1)
    if (spwm == 2) {
    #if (CONFIG_USING_SMPWM2_CC0 == 1)
    PWMPOL = (PWMPOL & ~(1 << 2)) | (CONFIG_SMPWM2_CC0_POLOR << 2);
    
    tmp = T2_MAX_CNT_VAL_GET() - (T2_MAX_CNT_VAL_GET() - TIMER2_RELOAD_VALUE) \
          * CONFIG_SMPWM2_CC0_INIT_DUTY / 100;
    PWM2CMPL = tmp & 0xff;
    PWM2CMPH = tmp >> 8;

    PWMEN = (PWMEN & ~(1 << 2)) | (1 << 2);
    spwm_cc_disable(2, 0);
    #endif

    #if (CONFIG_USING_SMPWM2_CC1 == 1)
    PWMPOL = (PWMPOL & ~(1 << 3)) | (CONFIG_SMPWM2_CC1_POLOR << 3);

    tmp = T2_MAX_CNT_VAL_GET() - (T2_MAX_CNT_VAL_GET() - TIMER2_RELOAD_VALUE) \
          * CONFIG_SMPWM2_CC1_INIT_DUTY / 100;
    PWM3CMPL = tmp & 0xff;
    PWM3CMPH = tmp >> 8;

    PWMEN = (PWMEN & ~(1 << 3)) | (1 << 3);
    spwm_cc_disable(2, 1);
    #endif 

    #if (CONFIG_USING_SMPWM2_CC2 == 1)
    PWMPOL = (PWMPOL & ~(1 << 4)) | (CONFIG_SMPWM2_CC2_POLOR << 4);

    tmp = T2_MAX_CNT_VAL_GET() - (T2_MAX_CNT_VAL_GET() - TIMER2_RELOAD_VALUE) \
          * CONFIG_SMPWM2_CC2_INIT_DUTY / 100;
    PWM4CMPL = tmp & 0xff;
    PWM4CMPH = tmp >> 8;          

    PWMEN = (PWMEN & ~(1 << 4)) | (1 << 4);
    spwm_cc_disable(2, 2);
    #endif 

    #if (CONFIG_USING_SMPWM2_CC3 == 1)
    PWMPOL = (PWMPOL & ~(1 << 5)) | (CONFIG_SMPWM2_CC3_POLOR << 5);

    tmp = T2_MAX_CNT_VAL_GET() - (T2_MAX_CNT_VAL_GET() - TIMER2_RELOAD_VALUE) \
          * CONFIG_SMPWM2_CC3_INIT_DUTY / 100;
    PWM5CMPL = tmp & 0xff;
    PWM5CMPH = tmp >> 8;          

    PWMEN = (PWMEN & ~(1 << 5)) | (1 << 5);
    spwm_cc_disable(2, 3); 
    #endif          

    #if (CONFIG_USING_SMPWM2_CC4 == 1)
    PWMPOL = (PWMPOL & ~(1 << 6)) | (CONFIG_SMPWM2_CC4_POLOR << 6);

    tmp = T2_MAX_CNT_VAL_GET() - (T2_MAX_CNT_VAL_GET() - TIMER2_RELOAD_VALUE) \
          * CONFIG_SMPWM2_CC4_INIT_DUTY / 100;
    PWM6CMPL = tmp & 0xff;
    PWM6CMPH = tmp >> 8;

    PWMEN = (PWMEN & ~(1 << 6)) | (1 << 6); 
    spwm_cc_disable(2, 4); 
    #endif      
    }
#endif
}

#if (CONFIG_USING_SMPWM0_CC0 == 1 || \
     CONFIG_USING_SMPWM2_CC0 == 1 || CONFIG_USING_SMPWM2_CC1 == 1 ||  \
     CONFIG_USING_SMPWM2_CC2 == 1 || CONFIG_USING_SMPWM2_CC3 == 1 ||  \
     CONFIG_USING_SMPWM2_CC4 == 1)
void spwm_cc_enable(uint8_t spwm, uint8_t cc)
{
#if (CONFIG_USING_SMPWM0 == 1)
    if (spwm == 0) {
    #if (CONFIG_USING_SMPWM0_CC0 == 1)
        if (cc == 0) {
            MFP2 = (MFP2 & 0x7c) | (1 << 0);
        }
    #endif
    }
#endif

#if (CONFIG_USING_SMPWM2 == 1)
    if (spwm == 2) {
#if (CONFIG_USING_SMPWM2_CC0 == 1)
        if (cc == 0) {
#if (CONFIG_SMPWM2_CC0_GPIO == 0x00)
            MFP3 = MFP3 & 0x9f;
            MFP0 = (MFP0 & 0xfc) | (1 << 0);
#elif (CONFIG_SMPWM2_CC0_GPIO == 0x02)
            MFP0 = (MFP0 & 0xcf) | (1 << 4);
#endif
        }
#endif

#if (CONFIG_USING_SMPWM2_CC1 == 1)
        if (cc == 1) {  
#if (CONFIG_SMPWM2_CC1_GPIO == 0x01)
            MFP0 = (MFP0 & 0xf3) | (1 << 2);
#elif (CONFIG_SMPWM2_CC1_GPIO == 0x03)
            MFP0 = (MFP0 & 0x3f) | (1 << 6);
#elif (CONFIG_SMPWM2_CC1_GPIO == 0x10)
            MFP2 = (MFP2 & 0x7c) | (1 << 7);            
#endif
        }
#endif

#if (CONFIG_USING_SMPWM2_CC2 == 1)
        if (cc == 2) { 
#if (CONFIG_SMPWM2_CC2_GPIO == 0x04)
            MFP1 = (MFP1 & 0xfc) | (1 << 0);       
#elif (CONFIG_SMPWM2_CC2_GPIO == 0x07)
            MFP1 = (MFP1 & 0x3f) | (1 << 6);
#endif           
        }
#endif    

#if (CONFIG_USING_SMPWM2_CC3 == 1)
        if (cc == 3) { 
#if (CONFIG_SMPWM2_CC3_GPIO == 0x05)
            MFP1 = (MFP1 & 0xf3) | (1 << 2);         
#elif (CONFIG_SMPWM2_CC3_GPIO == 0x14)
            MFP3 = (MFP3 & 0xfc) | (1 << 0);
#endif          
        }
#endif

#if (CONFIG_USING_SMPWM2_CC4 == 1)
        if (cc == 4) {  
#if (CONFIG_SMPWM2_CC4_GPIO == 0x06)
            MFP1 = (MFP1 & 0xcf) | (1 << 4);
#elif (CONFIG_SMPWM2_CC4_GPIO == 0x11)
            MFP2 = (MFP2 & 0xf3) | (1 << 2);                        
#elif (CONFIG_SMPWM2_CC4_GPIO == 0x12)
            MFP2 = (MFP2 & 0xcf) | (2 << 4);              
#endif           
        }
#endif          
    }
#endif
}

void spwm_cc_disable(uint8_t spwm, uint8_t cc)
{
#if (CONFIG_USING_SMPWM0 == 1)
    if (spwm == 0) {
#if (CONFIG_USING_SMPWM0_CC0 == 1)
        if (cc == 0) {
            GPIO_P1_0_4_OM_EN(0x01);
#if (CONFIG_SMPWM0_CC0_POLOR == 0)
            GPIO_P1_0_4_OUTPUT_LOW(0x01);
#elif (CONFIG_SMPWM0_CC0_POLOR == 1)
            GPIO_P1_0_4_OUTPUT_HIGH(0x01);
#endif        
            MFP2 &= 0x7c;
        }
#endif
    }
#endif

#if (CONFIG_USING_SMPWM2 == 1)
    if (spwm == 2) {
#if (CONFIG_USING_SMPWM2_CC0 == 1)
        if (cc == 0) { 
#if (CONFIG_SMPWM2_CC0_GPIO == 0x00)
            GPIO_P0_OM_EN(0x01);
#if (CONFIG_SMPWM2_CC0_POLOR == 0)
            GPIO_P0_OUTPUT_LOW(0x01);
#elif (CONFIG_SMPWM2_CC0_POLOR == 1)
            GPIO_P0_OUTPUT_HIGH(0x01);
#endif                  
            MFP3 = MFP3 & 0x9f;
            MFP0 = MFP0 & 0xfc;
#elif (CONFIG_SMPWM2_CC0_GPIO == 0x02)
            GPIO_P0_OM_EN(0x04);
#if (CONFIG_SMPWM2_CC0_POLOR == 0)
            GPIO_P0_OUTPUT_LOW(0x04);
#elif (CONFIG_SMPWM2_CC0_POLOR == 1)
            GPIO_P0_OUTPUT_HIGH(0x04);
#endif                  
            MFP0 &= 0xcf;
#endif
        }
#endif

#if (CONFIG_USING_SMPWM2_CC1 == 1)
        if (cc == 1) { 
#if (CONFIG_SMPWM2_CC1_GPIO == 0x01)
            GPIO_P0_OM_EN(0x02);
#if (CONFIG_SMPWM2_CC1_POLOR == 0)
            GPIO_P0_OUTPUT_LOW(0x02);
#elif (CONFIG_SMPWM2_CC1_POLOR == 1)
             GPIO_P0_OUTPUT_HIGH(0x02);
#endif                  
            MFP0 = (MFP0 & 0xf3);   
#elif (CONFIG_SMPWM2_CC1_GPIO == 0x03)
            GPIO_P0_OM_EN(0x08);
#if (CONFIG_SMPWM2_CC1_POLOR == 0)
            GPIO_P0_OUTPUT_LOW(0x08);
#elif (CONFIG_SMPWM2_CC1_POLOR == 1)
            GPIO_P0_OUTPUT_HIGH(0x08);
#endif                  
            MFP0 = (MFP0 & 0x3f);
#elif (CONFIG_SMPWM2_CC1_GPIO == 0x10)
            GPIO_P1_0_4_OM_EN(0x01);
#if (CONFIG_SMPWM2_CC1_POLOR == 0)
            GPIO_P1_0_4_OUTPUT_LOW(0x01);
#elif (CONFIG_SMPWM2_CC1_POLOR == 1)
            GPIO_P1_0_4_OUTPUT_HIGH(0x01);
#endif        
            MFP2 &= 0x7c;
#endif
        }
#endif

#if (CONFIG_USING_SMPWM2_CC2 == 1)
        if (cc == 2) {   
#if (CONFIG_SMPWM2_CC2_GPIO == 0x04)
            GPIO_P0_OM_EN(0x10);
#if (CONFIG_SMPWM2_CC2_POLOR == 0)
            GPIO_P0_OUTPUT_LOW(0x10);
#elif (CONFIG_SMPWM2_CC2_POLOR == 1)
            GPIO_P0_OUTPUT_HIGH(0x10);
#endif                  
            MFP1 = (MFP1 & 0xfc);       
#elif (CONFIG_SMPWM2_CC2_GPIO == 0x07)
            GPIO_P0_OM_EN(0x80);
#if (CONFIG_SMPWM2_CC2_POLOR == 0)
            GPIO_P0_OUTPUT_LOW(0x80);
#elif (CONFIG_SMPWM2_CC2_POLOR == 1)
            GPIO_P0_OUTPUT_HIGH(0x80);
#endif                  
            MFP1 = (MFP1 & 0x3f);          
#endif    
        }
#endif 

#if (CONFIG_USING_SMPWM2_CC3 == 1)
        if (cc == 3) { 
#if (CONFIG_SMPWM2_CC3_GPIO == 0x05)
            GPIO_P0_OM_EN(0x20);
#if (CONFIG_SMPWM2_CC3_POLOR == 0)
            GPIO_P0_OUTPUT_LOW(0x20);
#elif (CONFIG_SMPWM2_CC3_POLOR == 1)
            GPIO_P0_OUTPUT_HIGH(0x20);
#endif                  
            MFP1 = (MFP1 & 0xf3);            
#elif (CONFIG_SMPWM2_CC3_GPIO == 0x14)
            GPIO_P1_0_4_OM_EN(0x10);
#if (CONFIG_SMPWM2_CC3_POLOR == 0)
            GPIO_P1_0_4_OUTPUT_LOW(0x10);
#elif (CONFIG_SMPWM2_CC3_POLOR == 1)
            GPIO_P1_0_4_OUTPUT_HIGH(0x10);
#endif                  
            MFP2 &= 0x7c;
#endif           
        }
#endif

#if (CONFIG_USING_SMPWM2_CC4 == 1)            
        if (cc == 4) {   
#if (CONFIG_SMPWM2_CC4_GPIO == 0x06)
            GPIO_P0_OM_EN(0x40);
#if (CONFIG_SMPWM2_CC4_POLOR == 0)
            GPIO_P0_OUTPUT_LOW(0x40);
#elif (CONFIG_SMPWM2_CC4_POLOR == 1)
            GPIO_P0_OUTPUT_HIGH(0x40);
#endif                  
            MFP1 = (MFP1 & 0xcf);            
#elif (CONFIG_SMPWM2_CC4_GPIO == 0x11)
            GPIO_P1_0_4_OM_EN(0x02);
#if (CONFIG_SMPWM2_CC4_POLOR == 0)
            GPIO_P1_0_4_OUTPUT_LOW(0x02);
#elif (CONFIG_SMPWM2_CC4_POLOR == 1)
            GPIO_P1_0_4_OUTPUT_HIGH(0x02);
#endif                  
            MFP2 = (MFP2 & 0xf3);
#elif (CONFIG_SMPWM2_CC4_GPIO == 0x12)
            GPIO_P1_0_4_OM_EN(0x04);
#if (CONFIG_SMPWM2_CC4_POLOR == 0)
            GPIO_P1_0_4_OUTPUT_LOW(0x04);
#elif (CONFIG_SMPWM2_CC4_POLOR == 1)
            GPIO_P1_0_4_OUTPUT_HIGH(0x04);
#endif                  
            MFP2 = (MFP2 & 0xcf);
#endif            
        }    
#endif  
    }
#endif
}

void t2_set_duty(uint8_t cc, uint16_t duty)
{
    uint16_t cmp_val;

#if (CONFIG_USING_SMPWM2 == 1)
        cmp_val = T2_MAX_CNT_VAL_GET() - duty;

    #if (CONFIG_USING_SMPWM2_CC0 == 1)
        if (cc == 0) {
            PWM2CMPL = cmp_val & 0xff;
            PWM2CMPH = cmp_val >> 8;     
        }
    #endif

    #if (CONFIG_USING_SMPWM2_CC1 == 1)
        if (cc == 1) {
            PWM3CMPL = cmp_val & 0xff;
            PWM3CMPH = cmp_val >> 8;     
        }
    #endif

    #if (CONFIG_USING_SMPWM2_CC2 == 1)
        if (cc == 2) {
            PWM4CMPL = cmp_val & 0xff;
            PWM4CMPH = cmp_val >> 8;     
        }
    #endif

    #if (CONFIG_USING_SMPWM2_CC3 == 1)
        if (cc == 3) {
            PWM5CMPL = cmp_val & 0xff;
            PWM5CMPH = cmp_val >> 8;     
        }
    #endif

    #if (CONFIG_USING_SMPWM2_CC4 == 1)
        if (cc == 4) {
            PWM6CMPL = cmp_val & 0xff;
            PWM6CMPH = cmp_val >> 8;     
        }
    #endif    
#endif
}

// void spwm_set_duty_relative_max_val(uint8_t spwm, uint8_t cc, uint16_t duty)
// {
//     uint16_t cmp_val;

// #if (CONFIG_USING_SMPWM0 == 1)
//     if (spwm == 0) {
//         cmp_val = T0_MAX_CNT_VAL_GET() - duty;

//     #if (CONFIG_USING_SMPWM0_CC0 == 1)
//         if (cc == 0) {
//             PWM0CMPL = cmp_val & 0xff;
//             PWM0CMPH = cmp_val >> 8;     
//         }
//     #endif
//     }
// #endif

// #if (CONFIG_USING_SMPWM2 == 1)
//     if (spwm == 2) {
//         cmp_val = T2_MAX_CNT_VAL_GET() - duty;

//     #if (CONFIG_USING_SMPWM2_CC0 == 1)
//         if (cc == 0) {
//             PWM2CMPL = cmp_val & 0xff;
//             PWM2CMPH = cmp_val >> 8;     
//         }
//     #endif

//     #if (CONFIG_USING_SMPWM2_CC1 == 1)
//         if (cc == 1) {
//             PWM3CMPL = cmp_val & 0xff;
//             PWM3CMPH = cmp_val >> 8;     
//         }
//     #endif

//     #if (CONFIG_USING_SMPWM2_CC2 == 1)
//         if (cc == 2) {
//             PWM4CMPL = cmp_val & 0xff;
//             PWM4CMPH = cmp_val >> 8;     
//         }
//     #endif

//     #if (CONFIG_USING_SMPWM2_CC3 == 1)
//         if (cc == 3) {
//             PWM5CMPL = cmp_val & 0xff;
//             PWM5CMPH = cmp_val >> 8;     
//         }
//     #endif

//     #if (CONFIG_USING_SMPWM2_CC4 == 1)
//         if (cc == 4) {
//             PWM6CMPL = cmp_val & 0xff;
//             PWM6CMPH = cmp_val >> 8;     
//         }
//     #endif    
//     }
// #endif
// }
#endif

uint16_t spwm_get_max_duty(uint8_t spwm)
{
#if (CONFIG_USING_SMPWM0 == 1)
    if (spwm == 0)
        return T0_MAX_CNT_VAL_GET() - t0_reload_val_get();
#endif

#if (CONFIG_USING_SMPWM2 == 1)
    if (spwm == 2)
        return T2_MAX_CNT_VAL_GET() - t2_reload_val_get();  
#endif

    return 0;
}

#endif
#endif
